package com.dcy.system.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery;
import com.dcy.common.base.service.DcyBaseService;
import com.dcy.common.constant.RedisConstant;
import com.dcy.common.enums.RoleDataScopeEnum;
import com.dcy.common.model.PageModel;
import com.dcy.common.model.PageResult;
import com.dcy.system.convert.RoleConvert;
import com.dcy.system.dao.RoleDao;
import com.dcy.system.mapper.RoleDeptMapper;
import com.dcy.system.mapper.RoleResMapper;
import com.dcy.system.model.Role;
import com.dcy.system.model.RoleDept;
import com.dcy.system.model.RoleRes;
import com.dcy.system.vo.in.RoleCreateInVO;
import com.dcy.system.vo.in.RoleResourceInVO;
import com.dcy.system.vo.in.RoleSearchInVO;
import com.dcy.system.vo.in.RoleUpdateInVO;
import com.dcy.system.vo.out.RoleListOutVO;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author dcy
 * @since 2020-08-19
 */
@RequiredArgsConstructor
@Service
public class RoleService extends DcyBaseService {

    private final RoleResMapper roleResMapper;
    private final RoleDeptMapper roleDeptMapper;
    private final RoleDao roleDao;
    private final RoleConvert roleConvert = RoleConvert.INSTANCE;

    /**
     * 保存授权权限
     *
     * @param roleResourceInVO
     * @return
     */
    @CacheEvict(value = {RedisConstant.REDIS_USER_ROLE}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveAuthResource(RoleResourceInVO roleResourceInVO) {
        boolean success = false;
        if (StrUtil.isNotBlank(roleResourceInVO.getRoleId()) && roleResourceInVO.getResIds() != null) {
            // 删除关联表
            roleResMapper.delete(new LambdaQueryWrapper<RoleRes>().eq(RoleRes::getRoleId, roleResourceInVO.getRoleId()));
            // 添加关联表
            List<RoleRes> roleRes = new ArrayList<>();
            roleResourceInVO.getResIds().forEach(resId -> roleRes.add(new RoleRes().setRoleId(roleResourceInVO.getRoleId()).setResId(resId)));
            roleResMapper.insertBatchSomeColumn(roleRes);
            success = true;
        }
        return success;
    }

    /**
     * 获取表格数据
     *
     * @param roleSearchInVO
     * @param pageModel
     * @return
     */
    public PageResult<RoleListOutVO> pageListByEntity(RoleSearchInVO roleSearchInVO, PageModel pageModel) {
        return toPageResult(roleDao.pageListByEntity(roleConvert.toRole(roleSearchInVO), pageModel).convert(roleConvert::toOut));
    }

    /**
     * 获取全部信息
     *
     * @return
     */
    public List<RoleListOutVO> getAllRoleList() {
        return roleConvert.toOutList(roleDao.list());
    }

    /**
     * 添加角色数据以及自定义权限
     *
     * @param roleCreateInVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean save(RoleCreateInVO roleCreateInVO) {
        final Role role = roleConvert.toRole(roleCreateInVO);
        boolean success = roleDao.save(role);
        // 删除数据
        roleDeptMapper.delete(Wrappers.<RoleDept>lambdaQuery().eq(RoleDept::getRoleId, role.getId()));
        // 是否是自定义数据权限
        if (RoleDataScopeEnum.CUSTOM.getCode().equals(role.getDataScope()) && CollUtil.isNotEmpty(roleCreateInVO.getDeptIds())) {
            // 添加数据
            List<RoleDept> roleDepts = new ArrayList<>();
            roleCreateInVO.getDeptIds().forEach(s -> roleDepts.add(new RoleDept().setRoleId(role.getId()).setDeptId(s)));
            roleDeptMapper.insertBatchSomeColumn(roleDepts);
        }
        return success;
    }

    /**
     * 修改角色数据以及自定义权限
     *
     * @param roleUpdateInVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean update(RoleUpdateInVO roleUpdateInVO) {
        final Role role = roleConvert.toRole(roleUpdateInVO);
        boolean success = roleDao.updateById(role);
        // 删除数据
        roleDeptMapper.delete(Wrappers.<RoleDept>lambdaQuery().eq(RoleDept::getRoleId, role.getId()));
        // 是否是自定义数据权限
        if (RoleDataScopeEnum.CUSTOM.getCode().equals(role.getDataScope()) && CollUtil.isNotEmpty(roleUpdateInVO.getDeptIds())) {
            // 添加数据
            List<RoleDept> roleDepts = new ArrayList<>();
            roleUpdateInVO.getDeptIds().forEach(s -> roleDepts.add(new RoleDept().setRoleId(role.getId()).setDeptId(s)));
            roleDeptMapper.insertBatchSomeColumn(roleDepts);
        }
        return success;
    }

    /**
     * 删除角色
     *
     * @param id
     * @return
     */
    @CacheEvict(value = {RedisConstant.REDIS_USER_ROLE}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(String id) {
        boolean success = roleDao.removeById(id);
        // 删除数据
        roleDeptMapper.delete(Wrappers.<RoleDept>lambdaQuery().eq(RoleDept::getRoleId, id));
        return success;
    }

    /**
     * 批量删除角色
     *
     * @param idList
     * @return
     */
    @CacheEvict(value = {RedisConstant.REDIS_USER_ROLE}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBatchRole(List<String> idList) {
        boolean success = roleDao.removeByIds(idList);
        // 删除数据
        roleDeptMapper.delete(Wrappers.<RoleDept>lambdaQuery().in(RoleDept::getRoleId, idList));
        return success;
    }

    /**
     * 获取已授权的数据范围部门ids
     *
     * @param roleId
     * @return
     */
    public List<String> getDataScopeDeptIdsByRoleId(String roleId) {
        return SimpleQuery.list(Wrappers.<RoleDept>lambdaQuery().eq(RoleDept::getRoleId, roleId), RoleDept::getDeptId);
    }

}
